/*-------------------------------------------------------------------------
 *
 * fsm_internals.h
 *	  自由空间映射的内部函数
 *
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/include/storage/fsm_internals.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef FSM_INTERNALS_H
#define FSM_INTERNALS_H

#include "storage/buf.h"
#include "storage/bufpage.h"

/*
 * 一个FSM页面的结构。有关详细信息，请参见 src/backend/storage/freespace/README。
 */
typedef struct
{
	/*
	 * fsm_search_avail() 尝试通过以轮询方式将不同页面返回到不同的后端来分散多个后端的负载。
	 * fp_next_slot 指向要返回的下一个槽（假设该槽上有足够的空间满足请求）。它定义为int，
	 * 因为在没有独占锁的情况下更新它。虽然uint16更合适，但int更可能以原子方式
	 * 可获取/可存储。
	 */
	int			fp_next_slot;

	/*
	 * fp_nodes包含以数组存储的二叉树。前 NonLeafNodesPerPage 个元素是上层节点，
	 * 随后的 LeafNodesPerPage 个元素是叶子节点。未使用的节点为零。
	 */
	uint8		fp_nodes[FLEXIBLE_ARRAY_MEMBER];
} FSMPageData;

typedef FSMPageData *FSMPage;

/*
 * FSM页面上非叶子节点和叶子节点的数量，以及节点的总数。
 * 这些定义是fsmpage.c内部的。
 */
#define NodesPerPage (BLCKSZ - MAXALIGN(SizeOfPageHeaderData) - \
					  offsetof(FSMPageData, fp_nodes))

#define NonLeafNodesPerPage (BLCKSZ / 2 - 1)
#define LeafNodesPerPage (NodesPerPage - NonLeafNodesPerPage)

/*
 * FSM页面上FSM "槽"的数量。这是应该在fsmpage.c之外使用的数量。
 */
#define SlotsPerFSMPage LeafNodesPerPage

/* fsmpage.c中函数的原型 */
extern int	fsm_search_avail(Buffer buf, uint8 min_cat, bool advancenext,
							 bool exclusive_lock_held);
extern uint8 fsm_get_avail(Page page, int slot);
extern uint8 fsm_get_max_avail(Page page);
extern bool fsm_set_avail(Page page, int slot, uint8 value);
extern bool fsm_truncate_avail(Page page, int nslots);
extern bool fsm_rebuild_page(Page page);

#endif							/* FSM_INTERNALS_H */
